package com.hw.nio.netty.http;


import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

public class EventLoopTest {


    /**
     * 1.创建事件轮训组
     * 2.创建netty UDP管道
     * 3.绑定端口
     * 4.注册管道
     * 5.绑定端口和注册管道都是异步操作，可以添加监听器，监听完成后的动作
     * 6、给管道的pipeline中添加事件处理handler
     */
    @Test
    public void DatagramTest() throws IOException {

        NioEventLoopGroup eventExecutors = new NioEventLoopGroup(1);
        NioDatagramChannel nioDatagramChannel = new NioDatagramChannel();
        eventExecutors.register(nioDatagramChannel);
        ChannelFuture bind = nioDatagramChannel.bind(new InetSocketAddress(7788));
        bind.addListener((ChannelFutureListener) channelFuture -> System.out.println("绑定端口成功"));
        nioDatagramChannel.pipeline().addLast(new SimpleChannelInboundHandler<Object>() {
            @Override
            protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
                if(o instanceof DatagramPacket){
                    DatagramPacket datagramPacket = (DatagramPacket) o;
                    System.out.println(datagramPacket.content().toString(Charset.defaultCharset()));
                }
            }
        });
        System.in.read();
        eventExecutors.shutdownGracefully();
    }



    @Test
    public void serverSocketTest() throws IOException {
        NioEventLoopGroup boos = new NioEventLoopGroup(1);
        NioEventLoopGroup work = new NioEventLoopGroup(1);



        NioServerSocketChannel nioServerSocketChannel = new NioServerSocketChannel();
        boos.register(nioServerSocketChannel);
        nioServerSocketChannel.bind(new InetSocketAddress(8888));
        nioServerSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                super.channelRead(ctx, msg);
                System.out.println("读事件");
                if(msg instanceof NioSocketChannel){
                    NioSocketChannel nioSocketChannel = (NioSocketChannel) msg;
                    work.register(nioSocketChannel);
                    nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf o) throws Exception {
                            System.out.println(o.toString(Charset.defaultCharset()));
                            channelHandlerContext.channel().write(o.getByte(100));
                        }
                    });

                }
                System.out.println(msg.getClass().getName());
            }
        });

        System.in.read();
    }

    @Test
    public void httpServerTest() throws IOException {
        ServerBootstrap bootstrap = new ServerBootstrap();
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup work = new NioEventLoopGroup();
        bootstrap.group(boss,work);

        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel channel) throws Exception {
                ChannelPipeline pipeline = channel.pipeline();

                pipeline.addLast("decode",new HttpRequestEncoder());
                pipeline.addLast("aggregator",new HttpObjectAggregator(65536));

                pipeline.addLast("servlet", new SimpleChannelInboundHandler<Object>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
                        if (o instanceof FullHttpRequest) {
                            FullHttpRequest request= (FullHttpRequest) o;
                            System.out.println("url"+request.uri());
                            System.out.println(request.content().toString(Charset.defaultCharset()));

                            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.OK);
                            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8");
                            response.content().writeBytes("hello".getBytes());
                            ChannelFuture future = channelHandlerContext.writeAndFlush(response);
                            future.addListener(ChannelFutureListener.CLOSE);
                        }
                        if (o instanceof HttpRequest) {
                            HttpRequest request = (HttpRequest) o;
                            System.out.println("当前请求：" + request.uri());
                        }
                        if (o instanceof HttpContent) {
                            // 写入文件流
                            ByteBuf content = ((HttpContent) o).content();
                            OutputStream out = new FileOutputStream("/Users/tommy/temp/coderead-netty/target/test.mp4", true);
                            content.readBytes(out, content.readableBytes());
                            out.close();
                        }
                        if (o instanceof LastHttpContent) {
                            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, HttpResponseStatus.OK);
                            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=utf-8");
                            response.content().writeBytes("上传完毕".getBytes());
                            ChannelFuture future = channelHandlerContext.writeAndFlush(response);
                            future.addListener(ChannelFutureListener.CLOSE);
                        }
                    }
                });
                pipeline.addLast("encode",new HttpResponseEncoder());

            }
        });
        bootstrap.bind(6677);

        System.in.read();
    }



}
